package com.gzx.plugin.tjzy.modular.work.service.impl;

import java.io.File;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.shaded.com.google.common.collect.Lists;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.google.common.collect.Maps;
import com.gzx.data.feign.GzxDataFeign;
import com.gzx.data.feign.resp.GzxWxjkDdzwxxVo;
import com.gzx.plugin.tjzy.modular.util.SFtpUtil;
import com.gzx.plugin.tjzy.modular.work.bo.UserPayment;
import com.gzx.plugin.tjzy.modular.work.entity.vo.GzxMediatorWorkVo;
import com.gzx.plugin.tjzy.modular.work.mapper.GzxMediatorWorkMapper;
import com.gzx.plugin.tjzy.modular.work.service.GzxMediatorFtpService;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import vip.xiaonuo.common.tenant.TenantContext;
import vip.xiaonuo.common.util.CommonCryptogramUtil;
import vip.xiaonuo.common.util.CommonDateUtil;
import vip.xiaonuo.common.util.CommonRSAUtil;
import vip.xiaonuo.common.wechat.EmailExcelUtils;

/**
 * @author xbl
 */
@Slf4j
@Service
@DS("tjzy")
@RequiredArgsConstructor
public class GzxMediatorFtpServiceImpl implements GzxMediatorFtpService {

	private final GzxMediatorWorkMapper mediatorWorkMapper;

	private final GzxDataFeign dataFeign;

	@Value("${sftp.pubKey}")
	private String pubKey;

	@Value("${sftp.ip}")
	private String ip;

	@Value("${sftp.port}")
	private Integer port;

	@Value("${sftp.username}")
	private String username;

	@Value("${sftp.password}")
	private String password;

	@Value("${sftp.filePath}")
	private String filePath;

	private void processHistoryExcelData(boolean encrypt, String dateName, List<GzxMediatorWorkVo> excelList) {
		// 查到的数据部分内容要RSA加密，客户姓名，客户电话要加密，其中客户电话需要先脱敏再加密，库里存的电话是密文的
		if (CollUtil.isNotEmpty(excelList)) {
			for (GzxMediatorWorkVo mediatorWorkVo : excelList) {
				// 客户姓名
				if (ObjectUtils.isEmpty(mediatorWorkVo.getLiaisonName())) {
					// 客户姓名为空的跳过
					continue;
				} else {
					if (encrypt) {
						mediatorWorkVo.setLiaisonName(CommonRSAUtil.encrypt(mediatorWorkVo.getLiaisonName(), pubKey));
					}
				}
				// 客户电话
				if (!ObjectUtils.isEmpty(mediatorWorkVo.getLiaisonPhone())) {
					if (encrypt) {
						mediatorWorkVo.setLiaisonPhone(CommonRSAUtil.encrypt(
								CommonCryptogramUtil.doSm1AesDecrypt(mediatorWorkVo.getLiaisonPhone()), pubKey));
					}
				}
			}
		}
		List<JSONObject> jsonList = convertToJsonList(excelList);

		// 把加密后的数据放到excel里
		String excelPath = "";
		try {
			excelPath = EmailExcelUtils.createHistoryMediaWorkExcel(jsonList, dateName);
			log.info("催记数据生成excel成功，size:{},路径为：{}", jsonList.size(), excelPath);
		} catch (Exception e) {
			log.error("催记数据生成excel失败 ", e);
		}
		if (encrypt) {
			// 把excel发送到ftp服务器中 /upload/external/*找对接开发获取*/coll_action/yyyyMMdd/
			uploadToFtp(excelPath);
			// 发送完了把excel删除
			if (!ObjectUtils.isEmpty(excelPath)) {
				FileUtils.deleteQuietly(new File(excelPath));
			}
		}

	}

	public List<GzxMediatorWorkVo> findHistoryMedia(String start, String end) throws ParseException {
		List<GzxMediatorWorkVo> allDatas = Lists.newArrayList();
		// 催记数据
		int count = mediatorWorkMapper.getHistoryTotal(start, end);
		log.info("start:{},催记数据：{}", start, count);
		int batchSize = 1000;
		int totalPages = (count + batchSize - 1) / batchSize;
		for (int page = 1; page <= totalPages; page++) {
			// 分页查询数据（使用MyBatis分页）
			List<GzxMediatorWorkVo> batchDatas = mediatorWorkMapper.selectHistoryMediaWork(start, end,
					(page - 1) * batchSize, batchSize);
			if (CollUtil.isNotEmpty(batchDatas)) {
				// 根据 partnerBusinessId 去data_wxjk_ddzwxx表里用businessid查询custno（客户号码）
				List<String> partnerBusinessIdList = batchDatas.stream().map(GzxMediatorWorkVo::getPartnerBusinessId)
						.toList();
				long startTime = DateUtils.parseDate(start).getTime();
				String customStart = DateUtils.format(new Date(startTime - TimeUnit.DAYS.toMillis(30)),
						DateUtils.DATE_FORMAT_19);

				String custom = dataFeign.getCustomByDate(customStart, end, partnerBusinessIdList);
				if (ObjectUtils.isEmpty(custom)) {
					log.warn("从data库未查到custom数据");
				} else {
					List<GzxWxjkDdzwxxVo> customList = JSON.parseArray(custom, GzxWxjkDdzwxxVo.class);
					if (CollUtil.isNotEmpty(customList)) {
						Map<String, String> customMap = Maps.newHashMap();
						for (GzxWxjkDdzwxxVo customVo : customList) {
							if (ObjectUtils.isEmpty(customVo.getBusinessId())) {
								continue;
							}
							customMap.put(customVo.getBusinessId() + "", customVo.getCustCode());
						}
						// 把custom放到batchData里
						for (GzxMediatorWorkVo mediatorWorkVo : batchDatas) {
							if (customMap.containsKey(mediatorWorkVo.getPartnerBusinessId())) {
								String customCode = customMap.get(mediatorWorkVo.getPartnerBusinessId());
								mediatorWorkVo.setCustCode(customCode);
							}
							if (StringUtils.isEmpty(mediatorWorkVo.getLiaisonName())) {
								continue;
							}
							if (mediatorWorkVo.getRemark() == null) {
								mediatorWorkVo.setRemark("");
							}
							String remark = mediatorWorkVo.getRemark().trim();
							String resultCode = mediatorWorkVo.getResultCode();
							if (remark.indexOf("不认识") >= 0 || remark.indexOf("无声") >= 0 || remark.indexOf("拒接") >= 0
									|| remark.indexOf("停机") >= 0 || remark.indexOf("暂停服务") >= 0
									|| remark.indexOf("语音信箱") >= 0 || remark.indexOf("语音留言") >= 0 || remark.equals("接挂")
									|| remark.equals("语音") || remark.indexOf("语音助手") >= 0 || remark.indexOf("通话中") >= 0
									|| remark.indexOf("挂断") >= 0 || remark.indexOf("空号") >= 0
									|| remark.indexOf("接通无声") >= 0 || remark.indexOf("秒挂") >= 0) {//
								resultCode = "W06";

							}
							// W02,恶意拖欠或无能力还款
							if (remark.indexOf("不沟通") >= 0 || remark.indexOf("不说话") >= 0 || remark.indexOf("骂人挂机") >= 0
									|| remark.indexOf("提业务挂机") >= 0 || remark.indexOf("关机") >= 0
									|| remark.indexOf("不配合沟通") >= 0 || remark.indexOf("提平台挂") >= 0) {//
								resultCode = "W02";
							}
							// A01,承诺还款
							if (mediatorWorkVo.getPromiseRepaymentDay() != null
									&& mediatorWorkVo.getPromiseRepaymentDay().trim().length() > 0) {
								resultCode = "A01";
							}
							if (StringUtils.isEmpty(resultCode)) {
								resultCode = "W06";
								mediatorWorkVo.setRemark("");
							}
							mediatorWorkVo.setResultCode(resultCode);
							if (!StringUtils.isEmpty(mediatorWorkVo.getCustCode())
									|| !StringUtils.isEmpty(mediatorWorkVo.getPartnerBusinessId())) {
								allDatas.add(mediatorWorkVo);
							}
						}
						// 处理Excel数据（加密、生成Excel等）
					}
				}
				log.info("start:{},当前页：{}，数据条数：{}", start, page, batchDatas.size());
			}
		}
		return allDatas;
	}

	@Override
	public void syncHistoryMediaFtp(String start, String end, boolean encrypt) throws Exception {
		long startTime = DateUtils.parseDate(start).getTime();
		long endTime = DateUtils.parseDate(end).getTime();
		for (long time = startTime; time < endTime; time = time + TimeUnit.DAYS.toMillis(1)) {
			TenantContext.disableTenantFilter();
			String startParam = DateUtils.format(new Date(time), DateUtils.DATE_FORMAT_19);
			String endParam = DateUtils.format(new Date(time + TimeUnit.DAYS.toMillis(1)), DateUtils.DATE_FORMAT_19);
			log.info("start:{},end:{}", startParam, endParam);
			List<GzxMediatorWorkVo> saveDatas = findHistoryMedia(startParam, endParam);
			if (saveDatas.size() > 0) {
				processHistoryExcelData(encrypt, "fix-" + DateUtils.format(new Date(time), DateUtils.DATE_FORMAT_10),
						saveDatas);
			}
		}
	}

	@Override
	public void syncMediaFtp(boolean encrypt, String currentTime) throws Exception {
		log.info("催记：currentTime: {}", currentTime);
		// 当天有多少催记数据
		int count = mediatorWorkMapper.getDayTotal(currentTime);
		log.info("当前日期的催记数据为：{}", count);
		// 查询当天mediaWork数据，feign一批查2000个，每天维信催记1600左右
		int batchSize = 1000;
		// 计算总批次数
		int totalPages = (count + batchSize - 1) / batchSize;
		log.info("催记总页数：{}", totalPages);
		List<GzxMediatorWorkVo> allBatchDatas = Lists.newArrayList();
		for (int page = 1; page <= totalPages; page++) {
			TenantContext.disableTenantFilter();
			// 分页查询数据（使用MyBatis分页）
			List<GzxMediatorWorkVo> batchDatas = mediatorWorkMapper.selectDayMediaWork((page - 1) * batchSize,
					batchSize, currentTime);
			log.info("page:{},催记数据条数：{}", page, batchDatas.size());
			if (CollUtil.isNotEmpty(batchDatas)) {
				// 根据 partnerBusinessId 去data_wxjk_ddzwxx表里用businessid查询custno（客户号码）
				List<String> partnerBusinessIdList = batchDatas.stream().map(GzxMediatorWorkVo::getPartnerBusinessId)
						.toList();
				// 这里传太多会报错 org.mybatis.spring.MyBatisSystemException: null 因为参数过多sqlparser解析不出来
				long time = DateUtils.parseDate(currentTime).getTime();
				String customStart = DateUtils.format(new Date(time - TimeUnit.DAYS.toMillis(30)),
						DateUtils.DATE_FORMAT_19);
				String customEnd = DateUtils.format(new Date(time + TimeUnit.DAYS.toMillis(1)),
						DateUtils.DATE_FORMAT_19);
				String custom = dataFeign.getCustomByDate(customStart, customEnd, partnerBusinessIdList);
				if (ObjectUtils.isEmpty(custom)) {
					log.warn("催记从data库未查到custom数据");
				} else {
					List<GzxWxjkDdzwxxVo> customList = JSON.parseArray(custom, GzxWxjkDdzwxxVo.class);
					if (CollUtil.isNotEmpty(customList)) {
						Map<String, String> customMap = Maps.newHashMap();
						for (GzxWxjkDdzwxxVo customVo : customList) {
							if (ObjectUtils.isEmpty(customVo.getBusinessId())) {
								continue;
							}
							customMap.put(customVo.getBusinessId() + "", customVo.getCustCode());
						}

						// 把custom放到batchData里
						for (GzxMediatorWorkVo mediatorWorkVo : batchDatas) {
							if (customMap.containsKey(mediatorWorkVo.getPartnerBusinessId())) {
								String customCode = customMap.get(mediatorWorkVo.getPartnerBusinessId());
								mediatorWorkVo.setCustCode(customCode);
							}
							if (StringUtils.isEmpty(mediatorWorkVo.getResultCode())) {
								mediatorWorkVo.setResultCode("W06");
							}
						}
						allBatchDatas.addAll(batchDatas);
					}
				}
			}
		}

		// 处理Excel数据（加密、生成Excel等）
		if (allBatchDatas.size() > 0) {
			processExcelData(encrypt, allBatchDatas);
		}
	}

	// 加密excel部分列数据
	private void processExcelData(boolean encrypt, List<GzxMediatorWorkVo> excelList) {
		// 查到的数据部分内容要RSA加密，客户姓名，客户电话要加密，其中客户电话需要先脱敏再加密，库里存的电话是密文的
		if (CollUtil.isNotEmpty(excelList)) {
			for (GzxMediatorWorkVo mediatorWorkVo : excelList) {
				// 客户姓名
				if (ObjectUtils.isEmpty(mediatorWorkVo.getLiaisonName())) {
					// 客户姓名为空的跳过
					continue;
				} else {
					if (encrypt) {
						mediatorWorkVo.setLiaisonName(CommonRSAUtil.encrypt(mediatorWorkVo.getLiaisonName(), pubKey));
					}

				}
				// 客户电话
				if (!ObjectUtils.isEmpty(mediatorWorkVo.getLiaisonPhone())) {
					if (encrypt) {
						mediatorWorkVo.setLiaisonPhone(CommonRSAUtil.encrypt(
								CommonCryptogramUtil.doSm1AesDecrypt(mediatorWorkVo.getLiaisonPhone()), pubKey));
					}
				}
			}
		}

		log.info("催记加密之后的数据: {}", excelList.size());

		// 把List<GzxMediatorWorkVo> 转换成 List<JSONObject>
		List<JSONObject> jsonList = convertToJsonList(excelList);

		// 把加密后的数据放到excel里
		String excelPath = "";
		try {
			excelPath = EmailExcelUtils.createMediaWorkExcel(jsonList);
			log.info("催记数据生成excel成功，size:{},路径为：{}", jsonList.size(), excelPath);
		} catch (Exception e) {
			log.error("催记数据生成excel失败 ", e);
		}
		if (encrypt) {
			// 把excel发送到ftp服务器中 /upload/external/*找对接开发获取*/coll_action/yyyyMMdd/
			uploadToFtp(excelPath);

			// excel汇总文件发送到ftp服务器

			// 发送完了把excel删除
			if (!ObjectUtils.isEmpty(excelPath)) {
				FileUtils.deleteQuietly(new File(excelPath));
			}
		}

	}

	// 上传诉讼（调解协议）数据
	@Override
	public void transferFile(MultipartFile[] files) {
		String dir = filePath + "litigation_annex/" + CommonDateUtil.getYearMonthDateStr();
		log.info("上传诉讼数据: {}", dir);

		try {
			for (MultipartFile file : files) {
				String filePath = SFtpUtil.transferFile(file);
				log.info("上传诉讼（调解协议）数据-临时文件: {}", filePath);
				SFtpUtil.uploadFile(ip, port, username, password, filePath, dir, new File(filePath).getName());
				// 上传完了删除临时文件
				FileUtils.deleteQuietly(new File(filePath));
			}
		} catch (Exception e) {
			log.error("上传文件到sftp服务器失败: ", e);
		}
	}

	// 上传催记数据
	private void uploadToFtp(String fileName) {
		String dir = filePath + "coll_action/" + CommonDateUtil.getYearMonthDateStr();
		log.info("上传催记数据: {}", dir);

		try {
			SFtpUtil.uploadFile(ip, port, username, password, fileName, dir, new File(fileName).getName());
		} catch (Exception e) {
			log.error("催记上传文件到sftp服务器失败: ", e);
		}
	}

	// 类型转换
	public List<JSONObject> convertToJsonList(List<GzxMediatorWorkVo> voList) {
		List<JSONObject> jsonList = new ArrayList<>();
		for (GzxMediatorWorkVo vo : voList) {
			JSONObject json = JSON.parseObject(JSON.toJSONString(vo), JSONObject.class);
			jsonList.add(json);
		}
		return jsonList;
	}

	@Override
	public void check(List<UserPayment> payments) throws Exception {
		int count = 0;
		int timeoutCount = 0;
		Map<String, Integer> countMap = Maps.newTreeMap();
		Map<String, Integer> timeOutMap = Maps.newTreeMap();
		for (UserPayment payment : payments) {

			TenantContext.disableTenantFilter();
			int mediatorCount = mediatorWorkMapper.selectMediaWorkCountByBusinessId(payment.getBusinessId());

			if (mediatorCount == 0) {
				count++;
				Integer num = countMap.get(payment.getDate());
				if (num == null) {
					num = 0;
				}
				countMap.put(payment.getDate(), num + 1);
			} else {
				GzxMediatorWorkVo gzxMediatorWorkVo = mediatorWorkMapper
						.selectMediaWorkByBusinessId(payment.getDate() + " 00:00:00", payment.getBusinessId());
				if (gzxMediatorWorkVo == null) {
					timeoutCount++;
					Integer num = timeOutMap.get(payment.getDate());
					if (num == null) {
						num = 0;
					}
					timeOutMap.put(payment.getDate(), num + 1);
				}
			}
		}
		System.out.println("check end:" + payments.size() + ",count:" + count + ",timeoutCount:" + timeoutCount);
		System.out.println(countMap);
		System.out.println(timeOutMap);
	}

	@Override
	public void syncFixPayments(boolean encrypt, String rootDir) throws Exception {
		List<UserPayment> payments = PaymentsExcelReader.loadPayments(rootDir);
		List<GzxMediatorWorkVo> saveDatas = Lists.newArrayList();
		for (UserPayment payment : payments) {
			TenantContext.disableTenantFilter();
			int mediatorCount = mediatorWorkMapper.selectMediaWorkCountByBusinessId(payment.getBusinessId());
			if (mediatorCount > 0) {
				GzxMediatorWorkVo gzxMediatorWorkVo = mediatorWorkMapper
						.selectMediaWorkByBusinessId(payment.getDate() + " 00:00:00", payment.getBusinessId());
				if (gzxMediatorWorkVo != null) {
					gzxMediatorWorkVo.setRemark("");
					gzxMediatorWorkVo.setResultCode("A01");
					BigDecimal amount = BigDecimal.valueOf(Double.valueOf(payment.getAmount().replaceAll(",", "")));
					gzxMediatorWorkVo.setPromiseRepaymentAmount(amount);
					gzxMediatorWorkVo.setPromiseRepaymentDay(payment.getDate());
					saveDatas.add(gzxMediatorWorkVo);
				}
			}
		}
		if (saveDatas.size() > 0) {
			processHistoryExcelData(encrypt, "fix-" + DateUtils.format(new Date(), DateUtils.DATE_FORMAT_10),
					saveDatas);
		}
		log.info("补录用户支付催记数据，paymentsSize:{},uploadSize:{}", payments.size(), saveDatas.size());
	}

	@Override
	public void syncLitigationFile(String dateDir) throws Exception {
		String dir = filePath + "litigation_annex/" + dateDir;
		List<String> fileNames = SFtpUtil.getFiles(ip, port, username, password, filePath, dir);
		log.info("诉讼汇总文件 size:{}", fileNames.size());
		List<LitigationFile> dataList = Lists.newArrayList();
		for (String fileName : fileNames) {
			if (fileName.endsWith("pdf")) {
				int start = fileName.indexOf("-");
				int end = fileName.indexOf("."); 
				String businessId = fileName.substring(start + 1, end);
				LitigationFile data = new LitigationFile();
				data.setBusinessId(businessId);
				data.setFileName(fileName);
				data.setFileNote("file");
				dataList.add(data);
				log.info("诉讼汇总文件 fileName:{}", fileName);
			}
		}
		if (dataList.size() > 0) {
			String excelFile = ExcelLitigationFileWriter.createMExcel(dataList,
					DateUtils.format(new Date(), DateUtils.DATE_FORMAT_10));
			SFtpUtil.uploadFile(ip, port, username, password, excelFile, dir, new File(excelFile).getName());
			FileUtils.deleteQuietly(new File(filePath));
		}
	}
}
